package org.sky.sys.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.logging.log4j.Logger;
import org.sky.cache.JVMCached;
import org.sky.exception.ServiceException;
import org.sky.sys.entity.*;
import org.sky.sys.mapper.SysCommonMapper;
import org.sky.sys.mapper.SysRoleMapper;
import org.sky.sys.mapper.SysRoleResourceMapper;
import org.sky.sys.mapper.SysUserRoleMapper;
import org.sky.sys.util.BspUtils;
import org.sky.sys.util.TreeStru;
import org.sky.sys.util.page.PageListData;
import org.sky.sys.util.page.PageListDataUtils;
import org.sky.util.LogUtils;
import org.sky.util.SnowflakeIdWorker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * @author weifx
 * @Title: SysRoleService
 * @ProjectName springboot-platform
 * @Description: TODO{角色业务类}
 * @date 2019/3/1 11:15
 * @Version 1.0
 */
@Service
public class SysRoleService {
    private static Logger log = LogUtils.getLogger(SysRoleService.class);
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysRoleResourceMapper sysRoleResourceMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysCommonMapper sysCommonMapper;

    /**
     * 查询用户具有的角色
     * @param userCode
     * @return
     */
    public List<SysRole> selectSysRoleByUserCode(String userCode){
        return sysRoleMapper.selectSysRoleByUserCode(userCode);
    }

    /**
     * 角色分页查询
     * @param pageNum
     * @param pageSize
     * @param example
     * @return
     */
    public PageListData selectSysRoleByPage(int pageNum, int pageSize, Example example){
        PageHelper.startPage(pageNum, pageSize);
        final PageInfo<SysRole> pageInfo = new PageInfo<SysRole>(sysRoleMapper.selectByExample(example));
        return PageListDataUtils.getPageListData().setTotal(pageInfo.getTotal()).setRows(pageInfo.getList());
    }
    /**
     * 保存{新增/修改}角色
     * @param sysRole
     */
    public void saveAddEditSysRole(SysRole sysRole){
        try{
            Timestamp ts = sysCommonMapper.queryTimestamp();
            if(null == sysRole.getId()){
                //新增
                sysRole.setId(SnowflakeIdWorker.getInstance().nextId());
                sysRole.setCreater(BspUtils.getLoginUser().getCode());
                sysRole.setCreateTime(ts);
                sysRole.setUpdater(BspUtils.getLoginUser().getCode());
                sysRole.setUpdateTime(ts);
                sysRoleMapper.insertSelective(sysRole);
            }else{
                //修改
                sysRole.setUpdater(BspUtils.getLoginUser().getCode());
                sysRole.setUpdateTime(ts);
                Example example = new Example(SysRole.class);
                example.createCriteria().andEqualTo("id",sysRole.getId());
                sysRoleMapper.updateByExampleSelective(sysRole,example);
            }
        }catch(Exception e){
            log.error("用户保存失败:{}",e.getMessage());
            throw new ServiceException("用户保存失败",e);
        }
    }

    /**
     * 根据Id查询角色
     * @param id
     * @return
     */
    public SysRole getSysRoleById(Long id){
        Example example = new Example(SysRole.class);
        example.createCriteria().andEqualTo("id",id);
        return sysRoleMapper.selectOneByExample(example);
    }
    /**
     * 根据Id删除角色
     * @param delList
     */
    @Transactional
    public void delSysRoleById(List<SysRole> delList) throws ServiceException{
        try {
            for (SysRole del : delList) {
                //判断角色是否已经分配给用户
                Example ure = new Example(SysUserRole.class);
                ure.createCriteria().andEqualTo("roleCode",del.getCode());
                int count = sysUserRoleMapper.selectCountByExample(ure);
                if(count>0){
                    throw new ServiceException("角色"+del.getCode()+"已经分配给用户,不能删除");
                }
                //删除角色
                Example example = new Example(SysRole.class);
                example.createCriteria().andEqualTo("id", del.getId());
                sysRoleMapper.deleteByExample(example);
                //删除角色对应的资源
                Example srre = new Example(SysRoleResource.class);
                srre.createCriteria().andEqualTo("roleCode", del.getCode());
                sysRoleResourceMapper.deleteByExample(srre);
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("删除失败:{}",e.getMessage());
            throw new ServiceException("删除失败:"+e.getMessage(),e);
        }
    }

    /**
     * 查询角色资源树
     * @param roleCode
     * @return
     */
    public List<TreeStru> selectRoleResTree(String roleCode){
        Example example = new Example(SysRoleResource.class);
        example.createCriteria().andEqualTo("roleCode",roleCode);
        List<SysRoleResource> list = sysRoleResourceMapper.selectFullFieldByExample(example);
        List<TreeStru> tslist = new ArrayList();
        List<SysMenu> smlist = getSysMenuByParent("root");
        for(SysMenu sm:smlist){
            TreeStru ts = new TreeStru();
            ts.setId(sm.getId().toString());
            ts.setCode(sm.getCode());
            ts.setText(sm.getName());
            ts.setIconCls(sm.getIcon());
            ts.setData(sm);
            if(sm.getChildCount()>0){
                ts.setState("closed");
            }else{
                ts.setState("open");
            }
            tslist.add(ts);
            getRoleResTree(ts,list);
        }
        return tslist;
    }

    /**
     * 根据根据父节点编号查询所有菜单
     * @param parentCode
     * @return
     */
    private List<SysMenu> getSysMenuByParent(String parentCode){
        List<SysMenu> reslist = new ArrayList();
        List<SysMenu> smlist = JVMCached.getMenuList();
        for(SysMenu sm:smlist){
            if(parentCode.equals(sm.getParentCode())){
                reslist.add(sm);
            }
        }
        return reslist;
    }
    /**
     * 递归查询角色资源树
     * @param ts
     * @param srolist
     */
    private void getRoleResTree(TreeStru ts,List<SysRoleResource> srolist){
        SysMenu sm = (SysMenu)ts.getData();
        //如果不是叶子节点并且有下级则递归组装菜单
        if("0".equals(sm.getLeafFlag())&&
                sm.getChildCount()>0){
            List<SysMenu> smchild = getSysMenuByParent(sm.getCode());
            List<TreeStru> tslist = new ArrayList();
            for(SysMenu smc:smchild){
                TreeStru tsc = new TreeStru();
                tsc.setId(smc.getId().toString().toString());
                tsc.setCode(smc.getCode());
                tsc.setText(smc.getName());
                tsc.setIconCls(smc.getIcon());
                tsc.setData(smc);
                if(smc.getChildCount()>0){
                    tsc.setState("closed");
                }else{
                    tsc.setState("open");
                }
                tslist.add(tsc);
                getRoleResTree(tsc,srolist);
                ts.setChildren(tslist);
            }
        }else if("0".equals(sm.getLeafFlag())&&
                sm.getChildCount()==0){
            //如果不是叶子节点并且无下级菜单
            return;
        }else if("1".equals(sm.getLeafFlag())&&
                sm.getChildCount()>0){
            //如果是叶子节点并且有下级资源
            List<SysResource> solist = selectSysResourceByMenuCode(sm.getCode());
            List<TreeStru> tslist = new ArrayList();
            for(SysResource so:solist){
                TreeStru tsc = new TreeStru();
                tsc.setId(so.getId().toString());
                tsc.setCode(so.getCode());
                tsc.setText(so.getName());
                tsc.setIconCls("icon-resource");
                tsc.setChecked(roleHasResource(so,srolist));
                tsc.setData(so);
                tslist.add(tsc);
            }
            ts.setChildren(tslist);
            return;
        }else if("1".equals(sm.getLeafFlag())&&
                sm.getChildCount()==0){
            //是叶子节点并且无下级操作
            return;
        }
    }
    /**
     * 获取菜单下的所有资源
     * @param menuCode
     * @return
     */
    private List<SysResource> selectSysResourceByMenuCode(String menuCode){
        List<SysResource> reslist = new ArrayList();
        List<SysResource> solist = JVMCached.getResourceList();
        for(SysResource so:solist){
            if(menuCode.equals(so.getMenuCode())){
                reslist.add(so);
            }
        }
        return reslist;
    }

    /**
     * 判断角色是否已经具有资源
     * @param sr
     * @param srolist
     * @return
     */
    private boolean roleHasResource(SysResource sr,List<SysRoleResource> srolist){
        for(SysRoleResource srr:srolist){
            if(sr.getCode().equals(srr.getResCode())){
                return true;
            }
        }
        return false;
    }

    /**
     * 保存角色资源
     * @param role
     * @param solist
     * @throws ServiceException
     */
    @Transactional
    public void saveRoleResource(SysRole role,List<SysResource> solist) throws ServiceException{
        try{
            Example soe = new Example(SysRoleResource.class);
            soe.createCriteria().andEqualTo("roleCode",role.getCode());
            sysRoleResourceMapper.deleteByExample(soe);
            Timestamp ts = sysCommonMapper.queryTimestamp();
            for(SysResource so:solist){
                SysRoleResource sro = new SysRoleResource();
                sro.setId(SnowflakeIdWorker.getInstance().nextId());
                sro.setCreater(BspUtils.getLoginUser().getCode());
                sro.setCreateTime(ts);
                sro.setResCode(so.getCode());
                sro.setResUrl(so.getUrl());
                sro.setRoleCode(role.getCode());
                sro.setUpdater(BspUtils.getLoginUser().getCode());
                sro.setUpdateTime(ts);
                sysRoleResourceMapper.insertSelective(sro);
            }
        }catch(Exception e){
            log.error("角色{}增加资源失败:{}",role.getCode(),e.getMessage());
            throw new ServiceException("角色增加资源失败:"+e.getMessage());
        }
    }
}
